module sync_fifo #(
    parameter WIDTH = 1,
    parameter DEPTH_POWER = 1
) (
    input push_en_i,
    input pop_en_i,
    input [WIDTH-1:0] push_data_i,
    output [WIDTH-1:0] pop_data_o,
    output [DEPTH_POWER:0] level_o,
    output full_o,
    output empty_o,
    output reg overflow_o,
    output reg underflow_o,
    input clk,
    input rst_n
);

reg [WIDTH-1:0] mem [2**DEPTH_POWER-1:0];
reg [DEPTH_POWER:0] rd_idx;
reg [DEPTH_POWER:0] wr_idx;
always @(posedge clk,negedge rst_n) begin
    if(!rst_n) begin
        rd_idx <= 0;
        wr_idx <= 0;
    end
    else begin
        case ({push_en_i,pop_en_i})
            2'b11: begin
                mem[wr_idx] <= push_data_i;
                wr_idx <= wr_idx + 1;
                rd_idx <= rd_idx + 1;
            end
            2'b10: begin
                mem[wr_idx] <= push_data_i;
                wr_idx <= wr_idx + 1;
            end
            2'b01: begin
                rd_idx <= rd_idx + 1;
            end
        endcase
    end
end
assign pop_data_o = mem[rd_idx];
assign level_o = wr_idx - rd_idx;
assign full_o = level_o == 2**DEPTH_POWER;
assign empty_o = level_o == 0;
always @(posedge clk,negedge rst_n) begin
    if(!rst_n) begin
        overflow_o <= 0;
        underflow_o <= 0;
    end
    else if(full_o && push_en_i) overflow_o <= 1;
    else if(empty_o && pop_en_i) underflow_o <= 1;
end
endmodule